﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using HYCodeBase.Math;
using HYRevitCode.XYZUtility;

namespace Assist
{
	public class GeoUtil
	{
		public static bool IsEqual(double d1, double d2)
		{
			return MathUtility.IsEqual(d1, d2, 1E-05);
		}

		public static bool IsEqual(double d1, double d2, double dPrecision)
		{
			return MathUtility.IsEqual(d1, d2, dPrecision);
		}

		public static bool IsPointEqual(XYZ pt1, XYZ pt2)
		{
			return XYZUtilityMethod.IsPointEqual(pt1, pt2, 1E-05);
		}

		public static bool IsParallel(XYZ firstVec, XYZ secondVec)
		{
			return GeoUtil.IsSameDirection(firstVec, secondVec) || GeoUtil.IsOppositeDirection(firstVec, secondVec);
		}

		public static bool IsSameDirection(XYZ firstVec, XYZ secondVec)
		{
			return XYZUtilityMethod.IsSameDirection(firstVec, secondVec);
		}

		public static bool IsOppositeDirection(XYZ firstVec, XYZ secondVec)
		{
			return XYZUtilityMethod.IsOppositeDirection(firstVec, secondVec);
		}

		public static int GetPointQuadrant(XYZ ptStart, XYZ ptEnd, XYZ ptTest)
		{
			return XYZUtilityMethod.GetPointQuadrant(ptStart, ptEnd, ptTest);
		}

		public static void CompressPtsByDirect(UIApplication uiApp, List<XYZ> arPts)
		{
			bool flag = arPts.Count <= 2;
			if (!flag)
			{
				XYZ xyz = arPts.First<XYZ>();
				XYZ xyz2 = arPts.Last<XYZ>();
				List<XYZ> list = new List<XYZ>();
				while (arPts.Count > 1)
				{
					List<XYZ> list2 = new List<XYZ>();
					Line curve = uiApp.Application.CreatYJKLine(arPts.ElementAt(0), arPts.ElementAt(1), true);
					list2.Add(arPts.ElementAt(0));
					list2.Add(arPts.ElementAt(1));
					for (int i = 2; i < arPts.Count; i++)
					{
						XYZ xyz3 = arPts.ElementAt(i);
						XYZ closestPointTo = CurveAssistFunc.GetClosestPointTo(uiApp, curve, xyz3, true);
						bool flag2 = closestPointTo.DistanceTo(xyz3) < 1E-05;
						if (flag2)
						{
							list2.Add(xyz3);
						}
					}
					double num = 100000.0;
					double num2 = 0.0;
					XYZ item = null;
					XYZ item2 = null;
					XYZ xyz4 = list2.First<XYZ>() - (list2.Last<XYZ>() - list2.First<XYZ>()).Normalize() * 10000.0;
					for (int j = 0; j < list2.Count; j++)
					{
						double num3 = list2.ElementAt(j).DistanceTo(xyz4);
						bool flag3 = num3 < num;
						if (flag3)
						{
							num = num3;
							item = list2.ElementAt(j);
						}
						bool flag4 = num3 > num2;
						if (flag4)
						{
							num2 = num3;
							item2 = list2.ElementAt(j);
						}
						arPts.Remove(list2.ElementAt(j));
					}
					list.Add(item);
					list.Add(item2);
				}
				arPts.Clear();
				arPts.AddRange(list);
			}
		}

		public static void SortPointByDirect(UIApplication uiApp, List<XYZ> arPts, XYZ vtDir)
		{
			bool flag = arPts.Count < 2;
			if (!flag)
			{
				XYZ xyz = arPts.First<XYZ>() - vtDir;
				XYZ endOrDirection = arPts.First<XYZ>() + vtDir;
				Line curve = uiApp.Application.CreatYJKLine(xyz, endOrDirection, true);
				List<PointSort> list = new List<PointSort>();
				for (int i = 0; i < arPts.Count; i++)
				{
					PointSort pointSort = new PointSort();
					pointSort.pt = arPts.ElementAt(i);
					XYZ closestPointTo = CurveAssistFunc.GetClosestPointTo(uiApp, curve, arPts.ElementAt(i), true);
					pointSort.param = closestPointTo.DistanceTo(xyz);
					list.Add(pointSort);
				}
				PointComparer comparer = new PointComparer();
				list.Sort(comparer);
				arPts.Clear();
				for (int j = 0; j < list.Count; j++)
				{
					arPts.Add(list.ElementAt(j).pt);
				}
			}
		}

		public static void GetPolyBoundPts(List<XYZ> arPts, ref XYZ ptMin, ref XYZ ptMax)
		{
			XYZUtilityMethod.GetPolyBoundPts(arPts, ref ptMin, ref ptMax);
		}

		private static double multiply(XYZ p1, XYZ p2, XYZ p0)
		{
			return (p1.X - p0.X) * (p2.Y - p0.Y) - (p2.X - p0.X) * (p1.Y - p0.Y);
		}

		public static void GrahamScan(List<XYZ> arPts)
		{
			int index = 0;
			int count = arPts.Count;
			for (int i = 1; i < count; i++)
			{
				bool flag = arPts[i].Y < arPts[index].Y || (arPts[i].Y == arPts[index].Y && arPts[i].X < arPts[index].X);
				if (flag)
				{
					index = i;
				}
			}
			XYZ value = arPts[0];
			arPts[0] = arPts[index];
			arPts[index] = value;
			for (int i = 1; i < count - 1; i++)
			{
				index = i;
				for (int j = i + 1; j < count; j++)
				{
					bool flag2 = GeoUtil.multiply(arPts[j], arPts[index], arPts[0]) > 0.0 || (GeoUtil.multiply(arPts[j], arPts[index], arPts[0]) == 0.0 && arPts[0].DistanceTo(arPts[j]) < arPts[0].DistanceTo(arPts[index]));
					if (flag2)
					{
						index = j;
					}
				}
				value = arPts[i];
				arPts[i] = arPts[index];
				arPts[index] = value;
			}
		}

		public static LinkCurve GetLinkCurve(UIApplication uiApp)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			LinkCurve linkCurve = new LinkCurve();
			ModelOrDetailCurveFilter modelOrDetailCurveFilter = new ModelOrDetailCurveFilter();
			List<Reference> list = null;
			try
			{
				list = uiApp.ActiveUIDocument.Selection.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1, modelOrDetailCurveFilter, "请选择模型线或详图线作为沿线").ToList<Reference>();
			}
			catch
			{
				string text = "没有选择阵列沿线。";
				MessageBox.Show(text);
				throw new Exception(text);
			}
			LinkCurve result;
			try
			{
				bool flag = document.GetElement(list[0]) is ModelCurve;
				if (flag)
				{
					ModelCurve modelCurve = document.GetElement(list[0].ElementId) as ModelCurve;
					linkCurve.Add(modelCurve.GeometryCurve);
					foreach (Reference reference in list)
					{
						bool flag2 = document.GetElement(reference) is ModelCurve;
						if (flag2)
						{
							ModelCurve modelCurve2 = document.GetElement(reference) as ModelCurve;
							foreach (Reference reference2 in list)
							{
								bool flag3 = reference != reference2;
								if (flag3)
								{
									ModelCurve modelCurve3 = document.GetElement(reference2) as ModelCurve;
									bool flag4 = modelCurve3 != null;
									if (flag4)
									{
										IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
										modelCurve2.GeometryCurve.Intersect(modelCurve3.GeometryCurve, out intersectionResultArray);
										bool flag5 = intersectionResultArray != null;
										if (flag5)
										{
											IEnumerator enumerator3 = intersectionResultArray.GetEnumerator();
											{
												if (enumerator3.MoveNext())
												{
													IntersectionResult intersectionResult = (IntersectionResult)enumerator3.Current;
													try
													{
														XYZ hyendPoint = modelCurve2.GeometryCurve.GetEndPoint(0);
														XYZ hyendPoint2 = modelCurve2.GeometryCurve.GetEndPoint(1);
														bool flag6 = intersectionResult.XYZPoint.IsAlmostEqualTo(hyendPoint) || intersectionResult.XYZPoint.IsAlmostEqualTo(hyendPoint2);
														if (flag6)
														{
															bool flag7 = linkCurve.IsContains(uiApp, modelCurve2.GeometryCurve);
															if (flag7)
															{
																bool flag8 = !linkCurve.IsContains(uiApp, modelCurve3.GeometryCurve);
																if (flag8)
																{
																	linkCurve.Add(modelCurve3.GeometryCurve);
																}
															}
														}
													}
													catch
													{
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
				else
				{
					bool flag9 = document.GetElement(list[0]) is DetailCurve;
					if (flag9)
					{
						DetailCurve detailCurve = document.GetElement(list[0]) as DetailCurve;
						linkCurve.Add(detailCurve.GeometryCurve);
						foreach (Reference reference3 in list)
						{
							bool flag10 = document.GetElement(reference3) is DetailCurve;
							if (flag10)
							{
								DetailCurve detailCurve2 = document.GetElement(reference3) as DetailCurve;
								foreach (Reference reference4 in list)
								{
									bool flag11 = reference3 != reference4;
									if (flag11)
									{
										DetailCurve detailCurve3 = document.GetElement(reference4) as DetailCurve;
										bool flag12 = detailCurve3 != null;
										if (flag12)
										{
											IntersectionResultArray intersectionResultArray2 = new IntersectionResultArray();
											detailCurve2.GeometryCurve.Intersect(detailCurve3.GeometryCurve, out intersectionResultArray2);
											bool flag13 = intersectionResultArray2 != null;
											if (flag13)
											{
												IEnumerator enumerator6 = intersectionResultArray2.GetEnumerator();
												{
													if (enumerator6.MoveNext())
													{
														IntersectionResult intersectionResult2 = (IntersectionResult)enumerator6.Current;
														try
														{
															XYZ hyendPoint3 = detailCurve2.GeometryCurve.GetEndPoint(0);
															XYZ hyendPoint4 = detailCurve2.GeometryCurve.GetEndPoint(1);
															bool flag14 = intersectionResult2.XYZPoint.IsAlmostEqualTo(hyendPoint3) || intersectionResult2.XYZPoint.IsAlmostEqualTo(hyendPoint4);
															if (flag14)
															{
																bool flag15 = linkCurve.IsContains(uiApp, detailCurve2.GeometryCurve);
																if (flag15)
																{
																	bool flag16 = !linkCurve.IsContains(uiApp, detailCurve3.GeometryCurve);
																	if (flag16)
																	{
																		linkCurve.Add(detailCurve3.GeometryCurve);
																	}
																}
															}
														}
														catch
														{
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
				bool flag17 = linkCurve.Count < list.Count;
				if (flag17)
				{
					string message = "选择的集合中存在多条链接线或分支，请重新选择。";
					throw new Exception(message);
				}
				result = linkCurve;
			}
			catch (Exception)
			{
				string text2 = "选择的集合中存在多条链接线或分支，请重新选择。";
				MessageBox.Show(text2);
				throw new Exception(text2);
			}
			return result;
		}

		private const double precision = 1E-05;
	}
}
